package com.beidouapp.manager;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.csource.fastdfs.DownloadCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;

import com.beidouapp.common.util.SystemConfig;
import com.beidouapp.et.client.EtFactory;
import com.beidouapp.et.client.EtManager;
import com.beidouapp.et.client.api.IContext;
import com.beidouapp.et.client.api.IFile;
import com.beidouapp.et.client.callback.FileCallBack;
import com.beidouapp.et.client.callback.ICallback;
import com.beidouapp.et.client.callback.IReceiveListener;
import com.beidouapp.et.client.domain.DocumentInfo;
import com.beidouapp.et.client.domain.EtMsg;
import com.beidouapp.exception.BusinessException;
import com.boss.common.HttpUtils;
import com.boss.common.MD5Util;

public class IMClient {
	public static final Logger s_logger = LoggerFactory.getLogger(IMClient.class);
	private EtFactory etFactory;// = new com.beidouapp.et.client.EtFactory();
	private IContext ctx;
	private EtManager manager;
	private RedisTemplate redisTemplate;
	private IFile file;
	private String appKey;
	private String secretKey;
	private String clientId;
	private String domain;
	private String port;
	private final static String FAILURE = "1";
	private final static String SUCESS = "0";

	public String getDomain() {
		return domain;
	}

	public String getPort() {
		return port;
	}

	public void setRedisTemplate(RedisTemplate redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	public IMClient() {

	}

	public IMClient(String appKey, String secretKey, String clientId, String domain, String port) {
		super();
		this.appKey = appKey;
		this.secretKey = secretKey;
		this.clientId = clientId;
		this.domain = domain;
		this.port = port;
	}

	public String acquireAccessToken() {
		String ham_token = (String) redisTemplate.opsForValue().get(
				SystemConfig.getConfig("name.space") + "_" + SystemConfig.getConfig("ilink.imsc.uid") + "_ham_token");
		if (StringUtils.isNotEmpty(ham_token)) {
			return ham_token;
		}
		registInvokeURL();
		ham_token = getAccessTokenFromILinkS();
		return ham_token;
	}

	@SuppressWarnings("unchecked")
	public String getAccessTokenFromILinkS() {
		String account = SystemConfig.getConfig("ilink.imsc.uid");
		String ham_token = null;
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appkey", SystemConfig.getConfig("ilink.appkey"));
		params.put("secretkey", SystemConfig.getConfig("ilink.secretkey"));
		params.put("uid", account);
		params.put("token", "abcdefg");
		try {
			String value = HttpUtils.postJSON(SystemConfig.getConfig("ilink.ham.acquire.token.url"), params);
			JSONObject jo = JSONObject.fromObject(value);
			ham_token = jo.getString("access_token");
			String code = jo.optString("code", "");
			if (!SUCESS.equals(code)) {
				return null;
			}
			this.redisTemplate.opsForValue()
					.set(SystemConfig.getConfig("name.space") + "_" + SystemConfig.getConfig("ilink.imsc.uid")
							+ "_ham_token", ham_token,
							Long.parseLong(SystemConfig.getConfig("ilink.ham.token.timeout")), TimeUnit.SECONDS);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ham_token;
	}

	public void registInvokeURL() {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appkey", SystemConfig.getConfig("ilink.appkey"));
		params.put("secretkey", SystemConfig.getConfig("ilink.secretkey"));
		params.put("url", SystemConfig.getConfig("ilink.ham.invoke.url"));
		params.put("uid", SystemConfig.getConfig("ilink.imsc.uid"));
		params.put("token", "abcdefg");
		try {
			String code = HttpUtils.postJSON(SystemConfig.getConfig("ilink.ham.setconfig.url"), params);
			System.out.println(code);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws Exception {
		IMClient imClient = new IMClient("716498ec-ac61-046796", "ceb8447cc4ab78d2ec34cd9f11e4bed2", null,
				"lb.kaifakuai.com", "8085");
		DocumentInfo documentInfo=new DocumentInfo();
		documentInfo.setFileId("group2/M00/00/09/cEpgEVhmEkOAIPJkAAKDjlfSCYE953.doc");
		imClient.download(documentInfo, "C:/");
		
	}

	public Map<String, Object> addUser(String userName, String phoneNo) throws BusinessException {
		Map<String, Object> params = new HashMap<String, Object>();
		Map<String, Object> reMap = new HashMap<String, Object>();
		long epoch = System.currentTimeMillis();

		params.put("appkey", appKey);
		params.put("apptoken", MD5Util.MD5Encode(appKey + this.secretKey + epoch, null));
		params.put("nickname", userName);
		params.put("username", phoneNo);
		params.put("random", epoch);
		try {
			String IM_USER_ADDRESS = SystemConfig.getConfig("ilink.ham.adduser.url");
			String value = HttpUtils.post(IM_USER_ADDRESS, params);
			JSONObject re = JSONObject.fromObject(value);
			if (re.getInt("ret") != 0 && re.getInt("ret") != 7) {
				throw new BusinessException(re.getString("message"));
			}
			net.sf.json.JSONArray array = re.getJSONArray("userlist");
			for (int index = 0; index < array.size(); index++) {
				JSONObject dataInfo = array.getJSONObject(index);
				String userid = dataInfo.getString("userid");
				String type = dataInfo.getString("platformtype");
				reMap.put(type, userid);
			}
		} catch (IOException e) {
			s_logger.warn("Fail to add user,reason:" + e);
		}
		return reMap;
	}

	public static final String SEPCIAL_MSG_TYPE = "SEPCIAL";



	public String createGroup(String groupname, List<String> groupUsers) throws BusinessException {
		return createGroup(groupname, SystemConfig.getConfig("ilink.imsc.uid"), groupUsers);
	}

	public String createGroup(String groupname, String masterUser, List<String> groupUsers) throws BusinessException {
		try {
			String token = acquireAccessToken();
			Map params = new HashMap();
			params.put("send_uid", masterUser);
			params.put("group_name", groupname);
			params.put("action_type", 11);
			params.put("appkey", SystemConfig.getConfig("ilink.appkey"));
			params.put("username_list", groupUsers);
			String value = HttpUtils
					.postJSON(SystemConfig.getConfig("ilink.ham.group.create.url") + "?access_token=" + token, params);
			JSONObject returnJSON = JSONObject.fromObject(value);
			if (!"0".equals(returnJSON.getString("code"))) {
				throw new BusinessException(returnJSON.getString("message"));
			}
			String topic = returnJSON.getString("group_id");
			return topic;
			// long epoch = System.currentTimeMillis();
		} catch (Exception e) {
			throw new BusinessException(e.getMessage());
		}
	}

	public void deleteGroup(String groupId) throws BusinessException {
		try {
			Map params = new HashMap();
			params.put("appkey", SystemConfig.getConfig("ilink.appkey"));
			params.put("send_uid", SystemConfig.getConfig("ilink.imsc.uid"));
			params.put("group_id", groupId);
			params.put("action_type", 10);
			String token = acquireAccessToken();
			String result = HttpUtils
					.postJSON(SystemConfig.getConfig("ilink.ham.group.delete.url") + "?access_token=" + token, params);
			String code = JSONObject.fromObject(result).getString("code");
			if (!SUCESS.equals(code)) {
				throw new BusinessException("鍒犻櫎缁勫け璐�");
			}
		} catch (Exception e) {
			throw new BusinessException(e.getMessage());
		}
	}

	public void groupOption(String groupId, List<String> uid_list, int opt) throws BusinessException {

		try {
			Map params = new HashMap();
			params.put("send_uid", SystemConfig.getConfig("ilink.imsc.uid"));
			params.put("group_id", groupId);
			params.put("appkey", SystemConfig.getConfig("ilink.appkey"));
			params.put("action_type", opt);
			params.put("uid_list", uid_list);
			String token = acquireAccessToken();
			String result = HttpUtils.postJSON(
					SystemConfig.getConfig("ilink.ham.group.appenduser.url") + "?access_token=" + token, params);
			String code = JSONObject.fromObject(result).getString("code");
			if (!SUCESS.equals(code)) {
				throw new BusinessException("澧炲姞澶辫触!");
			}
		} catch (Exception e) {
			throw new BusinessException(e.getMessage());
		}

	}

	public void deleteGroupMember(String groupId, List<String> uid_list) throws BusinessException {
		groupOption(groupId, uid_list, 13);
	}

	public void appendGroupMember(String groupId, List<String> uid_list) throws BusinessException {
		groupOption(groupId, uid_list, 12);
	}

	// {groupId:"hamId","pageSize":"姣忛〉鐨勫ぇ灏�,"pageSeq":"绗灏戜釜鍒嗛〉","beginTime":"unixtime(unix鏃堕棿锛宨nt鏁存暟銆傛椂闂磋法搴︽渶澶氫负涓�釜鏈堛�濡傛灉瓒呰繃涓�釜鏈堬紝鏈嶅姟鍣ㄦ埅鏂�)","endtime":"unixtime","fromUser":"鍙戦�鑰呯殑username銆�
	// 鍙�"}
	public Map<String, Object> queryHistory(String groupId, int pageSize, int pageSeq, long beginTime, long endtime,
			String fromUser) {
		if(pageSeq==0){
			pageSeq=1;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		try {
			List<HamMessage> msgs = new ArrayList<HamMessage>();
			String token = acquireAccessToken();
			if (token == null) {
				throw new BusinessException("鍙戦�娑堟伅澶辫触!token鑾峰彇澶辫触!");
			}
			Map<String, Object> requestParams = new HashMap<String, Object>();
			requestParams.put("send_uid", SystemConfig.getConfig("ilink.imsc.uid"));

			requestParams.put("group_id", groupId);
			requestParams.put("page_seq", pageSeq);
			requestParams.put("page_size", pageSize);
			requestParams.put("begin_time", beginTime);
			requestParams.put("end_time", endtime);
			if (StringUtils.isNotEmpty(fromUser)) {
				requestParams.put("from", fromUser);
			}

			String key = "ilink.ham.query_history";
			String result = HttpUtils.postJSON(SystemConfig.getConfig(key) + "?access_token=" + token, requestParams);
			JSONObject returnData = JSONObject.fromObject(result);
			String code = returnData.getString("code");
			if (!SUCESS.equals(code)) {
				throw new BusinessException("鏌ヨ澶辫触!");
			}
			net.sf.json.JSONArray msg_list = returnData.getJSONArray("msg_list");
			Long count = returnData.getLong("count");
			for (int index = 0; index < msg_list.size(); index++) {
				JSONObject data = msg_list.getJSONObject(index);
				HamMessage msg = new HamMessage();
				msg.setContent(data.getString("content"));
				msg.setFrom(data.getString("from"));
				msg.setTime(data.getLong("time"));
				msgs.add(msg);
			}
			params.put("rs", msgs);
			params.put("count", count);
			return params;
		} catch (IOException e) {
			throw new BusinessException(e.getMessage());
		}
	}

/*	public void sendSysTopicMessage(JSONObject content, String msg_type, String... accept_uid) {
		sendTopicMessage(SystemConfig.getConfig("ilink.imsc.uid"), content, msg_type, "extra", accept_uid);
	}

	public void sendSysGroupMessage(JSONObject content, String msg_type, String... groupid) {
		sendTopicMessage(SystemConfig.getConfig("ilink.imsc.uid"), content, msg_type, "sgroup", groupid);
	}*/
/*
	public void sendTopicMessage(String send_uid, JSONObject content, String msg_type, String topic,
			String... accept_uid) {
		try {

			content.put("source_uid", send_uid);
			content.put("imsc_send_time", new Date().getTime());
//			content.put("msg", content);
			// content.put("dest_uid", accept_uid);
			content.put("msg_type", msg_type);
			String token = acquireAccessToken();
			if (token == null) {
				throw new BusinessException("鍙戦�娑堟伅澶辫触!token鑾峰彇澶辫触!");
			}
			Map<String, Object> requestParams = new HashMap<String, Object>();
			requestParams.put("send_uid", SystemConfig.getConfig("ilink.imsc.uid"));
			requestParams.put("to_list", accept_uid);
			requestParams.put("msg_type", 1);
			String key = "ilink.ham.send.msg.url";
			if (StringUtils.isNotEmpty(topic)) {
				requestParams.put("topic_type", topic);
				key = "ilink.ham.send.topicmsg.url";
			}
			requestParams.put("content", Base64.encode(content.toString()));

			String result = HttpUtils.postJSON(SystemConfig.getConfig(key) + "?access_token=" + token, requestParams);
			String code = JSONObject.fromObject(result).getString("code");
			if (!SUCESS.equals(code)) {
				throw new BusinessException("鍙戦�娑堟伅澶辫触!");
			}
		} catch (IOException e) {
			throw new BusinessException(e.getMessage());
		}

	}*/
	
/*	public void sendMessage(String send_uid, JSONObject content, String msg_type, String... accept_uid)
			throws BusinessException {
		sendTopicMessage(send_uid, content, msg_type, null, accept_uid);
	}*/

	public DocumentInfo upload(InputStream inputStream, String path) {
		FileOutputStream output = null;
		try {
			output = new FileOutputStream(path);
			int len = 0;
			byte[] bs = new byte[1024];
			while ((len = inputStream.read(bs)) != -1) {
				output.write(bs, 0, len);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		} finally {
			try {
				if (output != null)
					output.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return upload(path);

	}

	public DocumentInfo upload(String filePath) {
		DocumentInfo info = file.uploadFile(filePath, new FileCallBack() {

			@Override
			public void onSuccess(DocumentInfo arg0, String arg1) {
				System.out.println("success");
			}

			@Override
			public void onProcess(DocumentInfo arg0, String arg1, long arg2, long arg3) {
				System.out.println(arg2 + "  " + arg3);
			}

			@Override
			public void onFailure(String arg0, Throwable arg1) {
				s_logger.error("文件上传失败", arg1);
				throw new BusinessException("IM出现故障【 "+arg1.getMessage()+"】",arg1);
			}
		});
		return info; 
	}
	
	public void download(DocumentInfo info,String filePath) throws Exception{
		int success = file.downloadFile(info, filePath);
		if(success!=0){
			throw new BusinessException("Fail to download the file, errorCode:"+success);
		}
		
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void init() {
		etFactory = new EtFactory();
		/*ctx = etFactory.createContext();
		ctx.setAppKey(appKey).setSecretKey(secretKey).setUserName(clientId).setServerDomain(domain).setServerPort(port);
		String addUser = addUser("boss","boss");*/
		String userId = SystemConfig.getConfig("ilink.imsc.uid");
		IContext clientCtx = etFactory.createContext();
		clientCtx.setAppKey(appKey)
			.setSecretKey(secretKey)
			.setUserName(userId)
			.setServerDomain(domain)
			.setServerPort(port);
		manager = etFactory.create(clientCtx);
		manager.setConnectCallback(new ICallback(){
			@Override
			public void onSuccess(Object paramT) {
				/*im     = manager.getIm();*/
				file     = manager.getFile(); 
				s_logger.info("ilink连接成功");
			}

			@Override
			public void onFailure(Object paramT, Throwable paramThrowable) {
				// TODO Auto-generated method stub
				s_logger.error("ilink 服务器连接失败",paramThrowable);
			}
		});
		manager.setListener(new IReceiveListener(){
			@Override
			public void connectionLost(Throwable paramThrowable) {
				s_logger.error("IM发送信息失败",paramThrowable);
			}

			@Override
			public void onMessage(EtMsg paramEtMsg) {
			}
		});
		this.manager.connect();
	}

	
	public EtManager getManager() {
		return manager;
	}

	public String getAppKey() {
		return appKey;
	}

	public void setAppKey(String appKey) {
		this.appKey = appKey;
	}

	public String getSecretKey() {
		return secretKey;
	}

	public void setSecretKey(String secretKey) {
		this.secretKey = secretKey;
	}

	public String getClientId() {
		return clientId;
	}

	public void setClientId(String clientId) {
		this.clientId = clientId;
	}
}
